package http

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"strings"
)

var hopHeaders = []string{
	"Connection",          // Connection
	"Proxy-Connection",    // non-standard but still sent by libcurl and rejected by e.g. google
	"Keep-Alive",          // Keep-Alive
	"Proxy-Authenticate",  // Proxy-Authenticate
	"Proxy-Authorization", // Proxy-Authorization
	"Te",                  // canonicalized version of "TE"
	"Trailer",             // not Trailers per URL above; https://www.rfc-editor.org/errata_search.php?eid=4522
	"Transfer-Encoding",   // Transfer-Encoding
	"Upgrade",             // Upgrade
}

func DelRequestHeader(request *http.Request) {
	for _, h := range hopHeaders {
		request.Header.Del(h)
	}
}

func PrepareRequest(host string, req *http.Request) {
	DelRequestHeader(req)

	// do not proxy "Connection" header.
	req.Header.Del("Connection")
	// strip other unneeded headers.

	// alter other request params before sending them to upstream host
	req.Host = host
}

func BuildRequest(ctx *gin.Context, host string, schema string, uri string, query string) *http.Request {
	var r *http.Request
	fUrl := fmt.Sprintf("%s://%s%s", schema, host, uri)
	if len(query) > 0 {
		fUrl = fmt.Sprintf("%s?%s", fUrl, query)
	}

	// 2024/9/26 attempt to find
	//strRequestURI := string(ctx.Request.RequestURI)
	//rURL, _ := url.ParseRequestURI(strRequestURI)
	//fUrl = rURL.String()

	log.Println(fmt.Sprintf("prior to buildbing docker request: %s %s", ctx.Request.Method, fUrl))
	if strings.ToUpper(ctx.Request.Method) == "POST" {
		WorkThroughPostFormInitializationInGin(ctx)
		for key, values := range ctx.Request.PostForm {
			for _, value := range values {
				log.Printf("key:%s,value:%s pair is appended", key, value)
			}
		}
		if body := ctx.Request.PostForm.Encode(); len(body) > 0 {
			// submit the form
			r, _ = http.NewRequest(ctx.Request.Method, fUrl, strings.NewReader(body))
		} else {
			// transfer body
			r, _ = http.NewRequest(ctx.Request.Method, fUrl, ctx.Request.Body)
		}

	} else {
		r, _ = http.NewRequest(ctx.Request.Method, fUrl, ctx.Request.Body)
	}

	//originHeaders := ctx.Request.Header
	//for k, _ := range originHeaders {
	//	v := originHeaders.Get(k)
	//	r.Header.Add(k, v)
	//
	//	log.Printf("header appended: %s : %s", k, v)
	//}
	contentType := ctx.GetHeader("Content-Type")
	if len(contentType) > 0 {
		r.Header.Add("Content-Type", contentType)
	}

	return r
}

func WorkThroughPostFormInitializationInGin(ctx *gin.Context) {
	ctx.GetPostForm("none")
}

func NewHttpRequest(host string, schema string, uri string, query string) *http.Request {
	//fullUri := uri + "?" + query
	fullUri := uri
	r, _ := http.NewRequest("", fullUri, nil)

	PrepareRequest(host, r)
	r.URL.Scheme = schema
	r.Host = host

	return r
}

func ConvertRequest(ctx *gin.Context, r *http.Request, forServer bool) error {
	strRequestURI := ctx.Request.RequestURI

	r.Method = ctx.Request.Method
	r.Proto = "HTTP/1.1"
	r.ProtoMajor = 1
	r.ProtoMinor = 1
	r.ContentLength = ctx.Request.ContentLength
	//r.RemoteAddr = ctx.Request.RemoteAddr
	//r.Host = ctx.Request.Host
	r.TLS = ctx.Request.TLS
	r.Body = ctx.Request.Body
	//r.URL = ctx.Request.URL

	if forServer {
		r.RequestURI = strRequestURI
	}

	if r.Header == nil {
		r.Header = make(http.Header)
	} else if len(r.Header) > 0 {
		for k := range r.Header {
			delete(r.Header, k)
		}
	}

	for sk, sv := range ctx.Request.Header {
		switch sk {
		case "Transfer-Encoding":
			r.TransferEncoding = append(r.TransferEncoding, sv...)
		default:
			for _, svEle := range sv {
				r.Header.Set(sk, svEle)
			}

		}
	}

	return nil
}
